`timescale 1ns / 1ps

module fibonacci(
    input clk,
    input rst,
    input [3:0] n,
    output [31:0] result
    );

// a_w，b_w，f_w：用于连接寄存器文件和ALU的数据线。
// wd：写入寄存器文件的数据。
// ra1, ra2：寄存器文件的读地址。
// we：写使能信号。
// isf：选择信号，用于确定写入寄存器的数据是初始值还是来自ALU的计算结果。
// wa：写地址信号。
// count：计数器，跟踪当前计算的斐波那契数列项数。
// status：状态机的状态寄存器。
// op：ALU操作码。

    wire [31:0] a_w, b_w, f_w;
    wire [31:0] wd;
    reg [4:0] ra1, ra2;
    reg we=1'b0;
    reg isf;
    reg [4:0] wa;
    reg [3:0] count;
    reg [1:0] status;
    reg [3:0] op=4'b0001;

    assign wd = isf ? f_w : 32'b1;
    assign result = f_w;

    REGs reg_module_insts(
        .clk(clk),
        .raddr1(ra1),
        .rdata1(a_w),
        .raddr2(ra2),
        .rdata2(b_w),
        .waddr(wa),
        .wdata(wd),
        .we(we)
    );

    ALU alu_inst(
        .a(a_w),
        .b(b_w),
        .op(op),
        .f(f_w)
    );

    always @ (posedge clk) begin
        if (rst) begin
            count <= 4'b0010;
            status <= 2'b00;
        end
        else 
            case(status)
                2'b00: begin
                    isf <= 1'b0;
                    wa <= 5'b00001;
                    we <= 1'b1;
                    status <= 2'b01;
                end
                2'b01: begin
                    isf <= 1'b0;
                    wa <= 5'b00010;
                    we <= 1'b1;
                    ra1 <= 5'b00001;
                    ra2 <= 5'b00010;
                    status <= 2'b10;
                end
                2'b10: begin
                    isf <= 1'b1;
                    wa <= ra2 + 5'b00001;
                    we <= 1'b1;
                    count <= count + 4'b0001;
                    status <= 2'b11;
                end
                2'b11: begin
                    if(count < n) begin
                        ra1 <= ra1 + 5'b00001;
                        ra2 <= ra2 + 5'b00001;
                        we <= 1'b0;
                        status <= 2'b10;
                    end
                end
                default: begin
                    status <= 2'b00;
                end
            endcase
    end
    
initial
    $monitor($time, ,"fib2:status=%b", status);

//initial 
//    $monitor($time, ,"fib2:f=%d", f);
initial
    $monitor($time, ,"fib2:ral=%d, ra2=%d, count=%d", ra1, ra2, count);
initial
    $monitor($time, ,"fib2:wa=%d", wa);
initial
    $monitor($time, ,"fib2:wd=%h", wd);

endmodule
